#include <cstring>
#include <filesystem>
#include <gst/gst.h>
#include <iostream>
#include <string>

#include "camera.hpp"

/**
 * @brief 构造函数
 */
Camera::Camera()
{
}

/**
 * @brief 构造函数
 */
Camera::Camera(std::string url)
{
    this->url = url;
}

/**
 * @brief 析构函数
 */
Camera::~Camera()
{
}

/**
 * @brief 设置函数
 */
void Camera::set(std::string url)
{
    this->url = url;
}

/**
 * @brief 推流线程
 */
void Camera::thread()
{
    int argc = 0;
    char** argv = NULL;

    gst_init(&argc, &argv);

    GstElement* pipeline;
    GstElement* udpsrc;
    GstElement* queue;
    GstElement* rtpdepay;
    GstElement* h264parse;
    GstElement* flvmux;
    GstElement* rtmpsink;
    GstBus* bus;
    GstMessage* msg;

    // 创建 GStreamer 流水线
    pipeline = gst_pipeline_new("udp-to-rtmp");

    // 创建 GStreamer 元素
    udpsrc = gst_element_factory_make("udpsrc", "udpsrc");
    queue = gst_element_factory_make("queue", "queue");
    rtpdepay = gst_element_factory_make("rtph264depay", "rtph264depay");
    h264parse = gst_element_factory_make("h264parse", "h264parse");
    flvmux = gst_element_factory_make("flvmux", "flvmux");
    rtmpsink = gst_element_factory_make("rtmpsink", "rtmpsink");

    if (!pipeline || !udpsrc || !queue || !rtpdepay || !h264parse || !flvmux || !rtmpsink) {
        g_printerr("create pipeline failed!\n");
        return;
    }

    // 设置 udpsrc 属性 (接收 UDP 组播)
    g_object_set(G_OBJECT(udpsrc), "address", "230.1.1.1", NULL);
    g_object_set(G_OBJECT(udpsrc), "port", 1720, NULL);
    g_object_set(G_OBJECT(udpsrc), "multicast-iface", "eth0", NULL);
    g_object_set(G_OBJECT(udpsrc), "caps", gst_caps_from_string("application/x-rtp,media=video,encoding-name=H264"), NULL);

    // 设置 flvmux (使其支持实时流)
    g_object_set(G_OBJECT(flvmux), "streamable", TRUE, NULL);

    // 设置 RTMP 推流地址
    g_object_set(G_OBJECT(rtmpsink), "location", url.c_str(), NULL);

    // 组装管道
    gst_bin_add_many(GST_BIN(pipeline), udpsrc, queue, rtpdepay, h264parse, flvmux, rtmpsink, NULL);

    // 连接元素
    if (!gst_element_link_many(udpsrc, queue, rtpdepay, h264parse, flvmux, rtmpsink, NULL)) {
        g_printerr("link pipeline failed!\n");
        return;
    }

    // 启动管道
    gst_element_set_state(pipeline, GST_STATE_PLAYING);
    std::cout << "success: " << url << " start" << std::endl;

    // 监听消息总线
    bus = gst_element_get_bus(pipeline);
    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));

    // 处理错误消息
    if (msg != NULL) {
        GError* err;
        gchar* debug_info;

        switch (GST_MESSAGE_TYPE(msg)) {
        case GST_MESSAGE_ERROR:
            gst_message_parse_error(msg, &err, &debug_info);
            g_printerr("错误：%s\n", err->message);
            g_error_free(err);
            g_free(debug_info);
            break;
        case GST_MESSAGE_EOS:
            g_print("播放结束\n");
            break;
        default:
            break;
        }
        gst_message_unref(msg);
    }

    // 释放资源
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);
}

/**
 * @brief 启动推流
 */
void Camera::start()
{
    if (!handle.joinable()) {
        running = true;
        handle = std::thread(&Camera::thread, this);
    }
}

/**
 * @brief 关闭推流
 */
void Camera::stop()
{
    if (handle.joinable()) {
        running = false;
        handle.join();
    }
}
